package com.maylann.ratiocheater.encoder;


import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;

/**
 *  Encoder class for reading .torrent file.
 *
 */


public class Bcoder {


    static public void bencode(Object ob, OutputStream os) throws Exception {
		if (ob instanceof Integer) {
	
		    os.write ('i');
		    os.write (ob.toString().getBytes());
		    os.write ('e');
	
		} else if (ob instanceof ArrayList) {
	
		    os.write ('l');
		    Object[] ao = ((ArrayList)ob).toArray();

            for (Object anAo : ao) {
                bencode(anAo, os);
            }
	
		    os.write ('e');
		    
		} else if (ob instanceof LinkedHashMap) {
	
		    os.write ('d');
		    LinkedHashMap h = (LinkedHashMap)ob;
		    Object keys[] = h.keySet().toArray();

            for (Object r : keys) {
                bencode(((String) r).getBytes(), os);
                bencode(h.get(r), os);
            }
	
		    os.write ('e');
	
		} else if (ob instanceof byte[]) {
	
		    byte[] s = (byte[])ob;
		    Integer q = s.length;
		    os.write (q.toString().getBytes());
		    os.write (':');
		    os.write (s);
	
		} else {
		    throw new Exception ("bencode ?!");
		}
	
    }


    static public Object bdecode (InputStream is) throws Exception {
		int c;
	
		c = is.read ();
		
		if (c == 'e') {
		    
		    return null;
	
		} else if (c == 'i') {
		    
		    String s = "";
		    while ((c = is.read ()) != 'e') {
			    s += (char)c;
		    }
		    return Integer.parseInt(s);
	
		} else if (c == 'l') {
		    
		    ArrayList<Object> v = new ArrayList<Object>();
		    while (true) {
			Object g = bdecode(is);
			if (g == null)
                return v;
			else v.add(g);
		    }
	
		} else if (c == 'd') {
	
		    LinkedHashMap<String, Object> h = new LinkedHashMap<String, Object>();
		    while (true) {
                Object k = bdecode(is);
                if (k == null)
                    return h;
                else {
                    Object g = bdecode(is);
                    h.put(new String((byte[])k), g);
                }
		    }
	
		} else if ((c >= '0') && (c <= '9')) {
		    
		    String lng = "" + (char) c;
		    while ((c = is.read ()) != ':') {
			lng += (char)c;
		    }
	
		    int l = Integer.parseInt(lng);
		    byte[] cc = new byte[l];
		    for (int i = 0; i < l; i++) {
			cc[i] = (byte) (is.read());
		    }
		    return cc;
		}
		
		return null;
    }
    
    public static String urlencode(byte[] bs) {
        StringBuilder sb = new StringBuilder(bs.length*3);
        for (byte b : bs) {
            int c = b & 0xFF;
            sb.append('%');
            if (c < 16)
                sb.append('0');
            sb.append(Integer.toHexString(c));
        }
           
        return sb.toString();
    }
    
    public static String genPeerId(int[] bs) {
        StringBuilder sb = new StringBuilder(bs.length*3);
        for (int b : bs) {
            int c = b & 0xFF;
            if (c < 16)
                sb.append('0');
            sb.append(Integer.toHexString(c));
        }
           
        return sb.toString();
    }
}